Enable search by entity ID and area name in HAAppEntityAppIntentEntity#4075
Enable search by entity ID and area name in HAAppEntityAppIntentEntity#4075
Conversation
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
Updated the entity filtering logic to use case-insensitive and diacritic-insensitive matching for display string, entity ID, and area name. This enhances the search experience by making it more robust to user input variations.
There was a problem hiding this comment.
Pull request overview
This PR enhances the entity search functionality in App Intents by expanding search capabilities from just entity display names to include entity IDs and area names. This makes it easier for users to find entities using multiple search criteria, improving the overall user experience when working with App Intents and Shortcuts.
Key Changes:
- Modified the
entities(matching:)method to support multi-field search with case-insensitive matching - Added entity ID matching to complement existing display name search
- Added area name matching with nil-safe handling
| let matchDisplayString = entity.displayString.range( | ||
| of: string, | ||
| options: [.caseInsensitive, .diacriticInsensitive] | ||
| ) != nil | ||
| let matchEntityId = entity.entityId.range( | ||
| of: string, | ||
| options: [.caseInsensitive, .diacriticInsensitive] | ||
| ) != nil | ||
| let matchAreaName = { | ||
| if let area = entity.area { | ||
| return area.range(of: string, options: [.caseInsensitive, .diacriticInsensitive]) != nil |
There was a problem hiding this comment.
The implementation uses range(of:options:) with case-insensitive options, but the codebase consistently uses the simpler .lowercased().contains() pattern for case-insensitive string matching in similar contexts. Consider using the established pattern for consistency:
let matchDisplayString = entity.displayString.lowercased().contains(string.lowercased())
let matchEntityId = entity.entityId.lowercased().contains(string.lowercased())This pattern is used in other similar EntityQuery implementations like IntentCoverEntity, IntentLightEntity, IntentSwitchEntity, and ScriptAppIntent.
| let matchDisplayString = entity.displayString.range( | |
| of: string, | |
| options: [.caseInsensitive, .diacriticInsensitive] | |
| ) != nil | |
| let matchEntityId = entity.entityId.range( | |
| of: string, | |
| options: [.caseInsensitive, .diacriticInsensitive] | |
| ) != nil | |
| let matchAreaName = { | |
| if let area = entity.area { | |
| return area.range(of: string, options: [.caseInsensitive, .diacriticInsensitive]) != nil | |
| let matchDisplayString = entity.displayString.lowercased().contains(string.lowercased()) | |
| let matchEntityId = entity.entityId.lowercased().contains(string.lowercased()) | |
| let matchAreaName = { | |
| if let area = entity.area { | |
| return area.lowercased().contains(string.lowercased()) |
| let matchAreaName = { | ||
| if let area = entity.area { | ||
| return area.range(of: string, options: [.caseInsensitive, .diacriticInsensitive]) != nil | ||
| } else { | ||
| return false | ||
| } | ||
| }() |
There was a problem hiding this comment.
The immediately-invoked closure pattern for matchAreaName adds unnecessary complexity. Consider simplifying using optional chaining for better readability:
let matchAreaName = entity.area?.lowercased().contains(string.lowercased()) ?? falseThis is more concise and follows Swift idiomatic practices for handling optionals.
| let matchAreaName = { | |
| if let area = entity.area { | |
| return area.range(of: string, options: [.caseInsensitive, .diacriticInsensitive]) != nil | |
| } else { | |
| return false | |
| } | |
| }() | |
| let matchAreaName = entity.area?.range(of: string, options: [.caseInsensitive, .diacriticInsensitive]) != nil |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4075 +/- ##
=======================================
Coverage ? 45.78%
=======================================
Files ? 242
Lines ? 13621
Branches ? 0
=======================================
Hits ? 6236
Misses ? 7385
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
Extended entity search in App Intents to match against entity ID and area name in addition to entity display name.
Modified:
HAAppEntityAppIntentEntityQuery.entities(matching:)entityIdarea(with nil-safe handling)displayStringmatch using OR logicUsers can now search entities by:
Screenshots
N/A - Backend search logic change only
Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
Any other notes
None
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.